package com.woniuxy.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniuxy.utils.JWTUtil;
import com.woniuxy.utils.ResponseResults;
import com.woniuxy.utils.ResponseState;
import com.woniuxy.utils.TokenEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 该过滤器用来判断请求是否需要认证（登录）之后才能请求，
 * 判断请求头中是否有token，而且要合法才行；有且合法，放行，否则返回结果使其登录
 */
@Slf4j
//@Component
public class AuthFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        System.out.println("进入过滤器");
        // 1. 得到URI
        // uri: /abc/aa
        // url: http://xxx.xxx:xxx/abc/aa

        // 2. 判断URI是否需要登录后才能请求的。不是，登录；是，判断token
        HttpServletRequest request1 = (HttpServletRequest) request;
        String requestURI = request1.getRequestURI();
        System.out.println("输出请求的URI:" + requestURI);

        // todo 判断请求是否需要token认证
        if (requireAuth(requestURI)) {
            System.out.println("请求需要token认证");
            String token = request1.getHeader("authorization");
            System.out.println("token：" + token);

            // TODO 判断token是否为空
            if (token != null && token.length() > 0 && !token.equals("null")) {
                System.out.println("token不为空");
                // 有token，校验token是否合法
                if (JWTUtil.verify(token) == TokenEnum.TOKEN_SUCCESS) {
                    // token合法 放行
                    System.out.println("token合法，放行");
                    chain.doFilter(request, response);
                    // 返回值是void，下面代码不执行，return跳出
                    return;
                }
            }
            // token为空 或 token不合法
            // todo token验证未通过，需要（重新）登录
            ResponseResults<Object> responseResults = new ResponseResults<>()
                    .setCode(500)
                    .setState(ResponseState.NO_LOGIN)
                    .setMsg("请登录");
            // 将对象转换为json  jackson
            String json = new ObjectMapper().writeValueAsString(responseResults);
            HttpServletResponse response1 = (HttpServletResponse) response;
            response1.setHeader("Content-Type", "application/json;charset=utf-8");
            // 数据写到前端
            response1.getWriter().write(json);
            // 拒绝请求
            return;
        }
        System.out.println("请求不需要认证");
        // 放行
        chain.doFilter(request, response);
    }


    // 该方法用来验证当前请求是否需要认证才能访问，返回true表示需要
    private boolean requireAuth(String uri) {
        // 将所有不需要认证就能访问的rul写出来
        List<String> noAuthUris = Arrays.asList(
                "/user/login",
                "/user/regist",
//                "/goods/find",
                "/goods",
                "/goods/get",
                "/images/goods",
                "/order/pay/result",
                "/file/upload"
        );

        // 所有URI默认都需要认证
        AtomicBoolean flag = new AtomicBoolean(true);

        noAuthUris.forEach(str -> {
            if (uri.equals(str) || uri.startsWith(str)) {
                // 修改
                flag.set(false);
                return;
            }
        });

        // 如果此处返回的是false，值被修改，说明forEach中有uri匹配上了，需要放行
        return flag.get();
    }
}
